package com.huabo.weixin;

import com.huabo.weixin.model.*;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;

import javax.servlet.http.HttpServletRequest;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Created by Jackie Liu on 2017/8/25.
 */
public class WXmlHelper {

    public static final Logger log = Logger.getLogger(WXmlHelper.class);
    private String xmlStr;
    private Map<String, String> resultMap = new HashMap<String, String>();
    Document doc = null;

    public WXmlHelper(String xmlStr) {
        this.xmlStr = xmlStr;
        try {
            doc = DocumentHelper.parseText(xmlStr);
            xmlToMap();
        } catch (DocumentException e) {
            e.printStackTrace();
        }
    }

    public WXmlHelper(HttpServletRequest request) {
        StringBuffer sb = new StringBuffer();
        InputStreamReader isr = null;
        BufferedReader br = null;
        try {
            isr = new InputStreamReader(request.getInputStream(), "UTF-8");
            br = new BufferedReader(isr);
            String s = "";
            while ((s = br.readLine()) != null) {
                sb.append(s);
            }
            xmlStr = sb.toString();
            log.info(String.format("xmlStr : %s", xmlStr));
            if (StringUtils.isEmpty(xmlStr)) {
                return;
            }
            doc = DocumentHelper.parseText(xmlStr);
            xmlToMap();
        } catch (IOException e) {
            log.error(e);
        } catch (DocumentException e) {
            log.error(e);
        } finally {
            IOUtils.closeQuietly(isr);
            IOUtils.closeQuietly(br);
        }
    }

    public void xmlToMap() {
        if (doc == null) {
            return;
        }
        resultMap = new HashMap<String, String>();
        Element root = doc.getRootElement();
        List children = root.elements();
        for (int i = 0, size = children.size(); i < size; i ++) {
            Element element = (Element) children.get(i);
            String name = element.getName();
            String value = (String) element.getData();
            resultMap.put(name.toUpperCase(), value);
        }
    }

    private WXAcceptEventMessage rejectEventMessage(Map<String, String> resultMap) {
        WXAcceptEventMessage wxAcceptEventMessage = new WXAcceptEventMessage();
        wxAcceptEventMessage.setCreateTime(Long.valueOf(resultMap.get("CREATETIME") + "000"));
        wxAcceptEventMessage.setEvent(resultMap.get("EVENT"));
        wxAcceptEventMessage.setEventKey(resultMap.get("EVENTKEY"));
        wxAcceptEventMessage.setFromUserName(resultMap.get("FROMUSERNAME"));
        wxAcceptEventMessage.setMsgType(resultMap.get("MSGTYPE"));
        wxAcceptEventMessage.setTicket(resultMap.get("TICKET"));
        wxAcceptEventMessage.setToUserName(resultMap.get("TOUSERNAME"));
        return wxAcceptEventMessage;
    }

    /**
     * 获取用户关注事件(和扫描带参数二维码事件)的推送消息
     * @return
     */
    public WXAcceptEventMessage getWxAcceptSubscribeEventMessage() {
        if (resultMap == null || resultMap.get("EVENT") == null) {
            return null;
        }

        String event = resultMap.get("EVENT").toLowerCase();
        if (!"subscribe".equals(event) && !"scan".equals(event)) {
            return null;
        }
        return rejectEventMessage(resultMap);
    }

    /**
     * 获取用户取消关注事件的推送消息
     * @return
     */
    public WXAcceptEventMessage getWxAcceptUnSubscribeEventMessage() {
        if (resultMap == null || resultMap.get("EVENT") == null
                || !"unsubscribe".equals(resultMap.get("EVENT").toLowerCase())) {
            return null;
        }
        return rejectEventMessage(resultMap);
    }

    /**
     * 上报地理位置事件的推送消息
     * @return
     */
    public WXAcceptLocationEventMessage getWXAcceptLocationEventMessage() {
        if (resultMap == null || resultMap.get("EVENT") == null
                || !"location".equals(resultMap.get("EVENT").toLowerCase())) {
            return null;
        }

        WXAcceptLocationEventMessage wxAcceptLocationEventMessage = new WXAcceptLocationEventMessage();
        wxAcceptLocationEventMessage.setToUserName(resultMap.get("TOUSERNAME"));
        wxAcceptLocationEventMessage.setFromUserName(resultMap.get("FROMUSERNAME"));
        wxAcceptLocationEventMessage.setCreateTime(Long.valueOf(resultMap.get("CREATETIME") + "000"));
        wxAcceptLocationEventMessage.setMsgType(resultMap.get("MSGTYPE"));
        wxAcceptLocationEventMessage.setEvent(resultMap.get("EVENT"));
        wxAcceptLocationEventMessage.setLatitude(resultMap.get("LATITUDE"));
        wxAcceptLocationEventMessage.setLongitude(resultMap.get("LONGITUDE"));
        wxAcceptLocationEventMessage.setPrecision(resultMap.get("PRECISION"));
        return wxAcceptLocationEventMessage;
    }

    /**
     * 自定义菜单事件(点击菜单拉取消息时的事件推送、点击菜单跳转链接时的事件推送)的推送消息
     * @return
     */
    public WXAcceptMenuEventMessage getWXAcceptMenuClickEventMessage() {
        if (resultMap == null || resultMap.get("EVENT") == null) {
            return null;
        }

        String event = resultMap.get("EVENT").toLowerCase();
        if (!"click".equals(event) && !"view".equals(event)) {
            return null;
        }

        WXAcceptMenuEventMessage wxAcceptMenuEventMessage = new WXAcceptMenuEventMessage();
        wxAcceptMenuEventMessage.setToUserName(resultMap.get("TOUSERNAME"));
        wxAcceptMenuEventMessage.setFromUserName(resultMap.get("FROMUSERNAME"));
        wxAcceptMenuEventMessage.setCreateTime(Long.valueOf(resultMap.get("CREATETIME") + "000"));
        wxAcceptMenuEventMessage.setMsgType(resultMap.get("MSGTYPE"));
        wxAcceptMenuEventMessage.setEvent(resultMap.get("EVENT"));
        wxAcceptMenuEventMessage.setEventKey(resultMap.get("EVENTKEY"));
        return wxAcceptMenuEventMessage;
    }

    /**
     * 用户发送的文本消息
     * @return
     */
    public WXAcceptTextMessage getWXAcceptTextMessage() {
        if (resultMap == null || resultMap.get("MSGTYPE") == null
                || !"text".equals(resultMap.get("MSGTYPE").toLowerCase())) {
            return null;
        }
        WXAcceptTextMessage wxAcceptTextMessage = new WXAcceptTextMessage();
        wxAcceptTextMessage.setToUserName(resultMap.get("TOUSERNAME"));
        wxAcceptTextMessage.setFromUserName(resultMap.get("FROMUSERNAME"));
        wxAcceptTextMessage.setCreateTime(Long.valueOf(resultMap.get("CREATETIME") + "000"));
        wxAcceptTextMessage.setMsgType(resultMap.get("MSGTYPE"));
        wxAcceptTextMessage.setContent(resultMap.get("CONTENT"));
        wxAcceptTextMessage.setMsgId(resultMap.get("MSGID"));
        return wxAcceptTextMessage;
    }

    /**
     * 用户发送的图片消息
     * @return
     */
    public WXAcceptImageMessage getWXAcceptImageMessage() {
        if (resultMap == null || resultMap.get("MSGTYPE") == null
                || !"image".equals(resultMap.get("MSGTYPE").toLowerCase())) {
            return null;
        }
        WXAcceptImageMessage wxAcceptImageMessage = new WXAcceptImageMessage();
        wxAcceptImageMessage.setToUserName(resultMap.get("TOUSERNAME"));
        wxAcceptImageMessage.setFromUserName(resultMap.get("FROMUSERNAME"));
        wxAcceptImageMessage.setCreateTime(Long.valueOf(resultMap.get("CREATETIME") + "000"));
        wxAcceptImageMessage.setMsgType(resultMap.get("MSGTYPE"));
        wxAcceptImageMessage.setPicUrl(resultMap.get("PICURL"));
        wxAcceptImageMessage.setMediaId(resultMap.get("MEDIAID"));
        wxAcceptImageMessage.setMsgId(resultMap.get("MSGID"));
        return wxAcceptImageMessage;
    }

    /**
     * 用户发送的语音消息
     * @return
     */
    public WXAcceptVoiceMessage getWXAcceptVoiceMessage() {
        if (resultMap == null || resultMap.get("MSGTYPE") == null
                || !"voice".equals(resultMap.get("MSGTYPE").toLowerCase())) {
            return null;
        }
        WXAcceptVoiceMessage wxAcceptVoiceMessage = new WXAcceptVoiceMessage();
        wxAcceptVoiceMessage.setToUserName(resultMap.get("TOUSERNAME"));
        wxAcceptVoiceMessage.setFromUserName(resultMap.get("FROMUSERNAME"));
        wxAcceptVoiceMessage.setCreateTime(Long.valueOf(resultMap.get("CREATETIME") + "000"));
        wxAcceptVoiceMessage.setMsgType(resultMap.get("MSGTYPE"));
        wxAcceptVoiceMessage.setFormat(resultMap.get("FORMAT"));
        wxAcceptVoiceMessage.setMediaId(resultMap.get("MEDIAID"));
        wxAcceptVoiceMessage.setMsgId(resultMap.get("MSGID"));
        wxAcceptVoiceMessage.setRecognition(resultMap.get("RECOGNITION"));
        return wxAcceptVoiceMessage;
    }

    /**
     * 用户发送的视频消息
     * @return
     */
    public WXAcceptVideoMessage getWXAcceptVideoMessage() {
        if (resultMap == null || resultMap.get("MSGTYPE") == null) {
            return null;
        }

        String msgType = resultMap.get("MSGTYPE").toLowerCase();
        if (!"video".equals(msgType) && !"shortvideo".equals(msgType)) {
            return null;
        }

        WXAcceptVideoMessage wxAcceptVideoMessage = new WXAcceptVideoMessage();
        wxAcceptVideoMessage.setToUserName(resultMap.get("TOUSERNAME"));
        wxAcceptVideoMessage.setFromUserName(resultMap.get("FROMUSERNAME"));
        wxAcceptVideoMessage.setCreateTime(Long.valueOf(resultMap.get("CREATETIME") + "000"));
        wxAcceptVideoMessage.setMsgType(resultMap.get("MSGTYPE"));
        wxAcceptVideoMessage.setMediaId(resultMap.get("MEDIAID"));
        wxAcceptVideoMessage.setThumbMediaId(resultMap.get("THUMBMEDIAID"));
        wxAcceptVideoMessage.setMsgId(resultMap.get("MSGID"));
        return wxAcceptVideoMessage;
    }

    /**
     * 用户发送的地理位置消息
     * @return
     */
    public WXAcceptLocationMessage getWXAcceptLocationMessage() {
        if (resultMap == null || resultMap.get("MSGTYPE") == null
                || !"location".equals(resultMap.get("MSGTYPE").toLowerCase())) {
            return null;
        }

        WXAcceptLocationMessage wxAcceptLocationMessage = new WXAcceptLocationMessage();
        wxAcceptLocationMessage.setToUserName(resultMap.get("TOUSERNAME"));
        wxAcceptLocationMessage.setFromUserName(resultMap.get("FROMUSERNAME"));
        wxAcceptLocationMessage.setCreateTime(Long.valueOf(resultMap.get("CREATETIME") + "000"));
        wxAcceptLocationMessage.setMsgType(resultMap.get("MSGTYPE"));
        wxAcceptLocationMessage.setLocationX(resultMap.get("LOCATION_X"));
        wxAcceptLocationMessage.setLocationY(resultMap.get("LOCATION_Y"));
        wxAcceptLocationMessage.setScale(resultMap.get("SCALE"));
        wxAcceptLocationMessage.setLabel(resultMap.get("LABEL"));
        wxAcceptLocationMessage.setMsgId(resultMap.get("MSGID"));
        return wxAcceptLocationMessage;
    }

    /**
     * 用户发送的链接消息
     * @return
     */
    public WXAcceptLinkMessage getWXAcceptLinkMessage() {
        if (resultMap == null || resultMap.get("MSGTYPE") == null
                || !"link".equals(resultMap.get("MSGTYPE").toLowerCase())) {
            return null;
        }

        WXAcceptLinkMessage wxAcceptLinkMessage = new WXAcceptLinkMessage();
        wxAcceptLinkMessage.setToUserName(resultMap.get("TOUSERNAME"));
        wxAcceptLinkMessage.setFromUserName(resultMap.get("FROMUSERNAME"));
        wxAcceptLinkMessage.setCreateTime(Long.valueOf(resultMap.get("CREATETIME") + "000"));
        wxAcceptLinkMessage.setMsgType(resultMap.get("MSGTYPE"));
        wxAcceptLinkMessage.setTitle(resultMap.get("TITLE"));
        wxAcceptLinkMessage.setDescription(resultMap.get("DESCRIPTION"));
        wxAcceptLinkMessage.setUrl(resultMap.get("URL"));
        wxAcceptLinkMessage.setMsgId(resultMap.get("MSGID"));
        return wxAcceptLinkMessage;
    }

    public static void main(String[] args) {
        String xml = "<xml><ToUserName><![CDATA[toUser]]></ToUserName>" +
                "<FromUserName><![CDATA[FromUser]]></FromUserName>" +
                "<CreateTime>123456789</CreateTime>" +
                "<MsgType><![CDATA[event]]></MsgType>" +
                "<Event><![CDATA[subscribe]]></Event>" +
                "<EventKey><![CDATA[qrscene_123123]]></EventKey>" +
                "<Ticket><![CDATA[TICKET]]></Ticket>" +
                "</xml>";
        WXmlHelper xmlHelper = new WXmlHelper(xml);
        //System.out.println(xmlHelper.xmlToMap());
    }
}
